﻿using LightCAD.MathLib;
using LightCAD.Three;
using System;
using System.Collections.Generic;
using System.Diagnostics.Metrics;
using System.Linq;
using System.Net;
using System.Reactive.Joins;
using System.Xml.Schema;
using static System.Runtime.InteropServices.JavaScript.JSType;
using GeometryData = LightCAD.Model.GeometryData;

namespace QdStruct
{
    public class ColumnAction : ComponentInstance2dAction
    {
        private PointInputer PointInputer { get; set; }
        private QdColumnInstance _columnInstance = null;
        public static LcCreateMethod[] CreateMethods;
        /// <summary>
        /// 轮廓第一个点
        /// </summary>
        private Vector2? firstPoint { get; set; }
        /// <summary>
        /// 当前绘制线段类型
        /// </summary>
        private string CurrentType = "Line";
        private double SweepAngle = Math.PI;
        /// <summary>
        /// 当前圆心画圆曲线
        /// </summary>
        private Arc2d CurrentArc;
        private List<Curve2d> Segments;
        public ColumnAction() { }
        public ColumnAction(IDocumentEditor docEditor) : base(docEditor) 
        {
            this.commandCtrl.WriteInfo("命令：Column");
        }
        static ColumnAction()
        {

            CreateMethods = new LcCreateMethod[3];
            CreateMethods[0] = new LcCreateMethod()
            {
                Name = "CreateColumnSection",
                Description = "创建柱截面轮廓",
                Steps = new LcCreateStep[]
                {
                    new LcCreateStep { Name=  "Step0", Options= "指定起点或[圆柱(C)]:" },
                    new LcCreateStep { Name=  "Step1", Options= "下一个点或[圆弧(A)/放弃(U)]:" },
                    new LcCreateStep { Name=  "Step2", Options= "下一个点或[圆弧(A)/闭合(C)/放弃(U)/]:" },
                    new LcCreateStep { Name=  "Step3", Options= "[角度(A)/圆心(CE)/半径(R)/第二个点(S)/直线(L)/放弃(U)]:" },
                    new LcCreateStep { Name=  "Step4", Options= "[角度(A)/圆心(CE)/闭合(CL)/直线(L)/半径(R)/第二个点(S)/放弃(U)]:" },
                    new LcCreateStep { Name=  "Step5", Options= "指定圆弧的圆心:" },
                    new LcCreateStep { Name=  "Step6", Options= "指定圆弧的端点或 [角度(A)/长度(L)/切换方向(C)/]:" },
                    new LcCreateStep { Name=  "Step7", Options= "指定夹角:" },
                    new LcCreateStep {Name="Step8",Options="指定圆弧的端点(按住 Ctrl 键以切换方向)或 [圆心(CE)/半径(R)]:"},
                    new LcCreateStep { Name=  "Step9", Options= "指定圆弧的端点或 [角度(A)/长度(L)/切换方向(C)/闭合(CL)]:" },
                    new LcCreateStep { Name=  "Step10", Options= "指定圆的圆心:" },
                    new LcCreateStep { Name=  "Step11", Options= "指定圆上任意一点:" },

                }
            };
        }
        private async Task<bool> Creating(LcCreateMethod curMethod, List<Curve2d> curSg)
        {
        Step0:
            this.CurrentType = "Line";
            var step0 = curMethod.Steps[0];
            var result0 = await PointInputer.Execute(step0.Options);
            if (PointInputer.isCancelled)
            {
                return false;
            }
            if (result0.ValueX != null)
            {
                this.firstPoint = (Vector2)result0.ValueX;
            }
            else
            if (result0.Option != null)
            {
                if (result0.Option.ToUpper() == "C")
                {
                    goto Step10;
                }
                var opv = GetOptionVector(result0.Option);
                if (opv!=null)
                {
                    this.firstPoint = opv;
                }
                else
                {
                    goto Step0;
                }
            } 
        Step1:
            this.CurrentType = "Line";
            var step1 = curMethod.Steps[1];
            var result1 = await PointInputer.Execute(step1.Options);
            if (PointInputer.isCancelled)
            {
                return false;
            }
        Step1ValueX:
            if (result1.ValueX != null)
            {
                Vector2 pointB = (Vector2)result1.ValueX;
                Line2d pline = new Line2d();
                if (curSg.Count > 0)
                {
                    var lastLine = curSg.Last();
                    var endPoint = lastLine is Line2d ? (lastLine as Line2d).End : (lastLine as Arc2d).GetPoints(1).Last();
                    pline.Start = endPoint.Clone();
                }
                else
                {
                    pline.Start = this.firstPoint.Clone();
                }
                pline.End = pointB.Clone();
                curSg.Add(pline);
                if (curSg.Count > 1)
                {
                    goto Step2;
                }
                goto Step1;
            }
            else
            if (result1.Option != null)
            {
                var opvec = GetOptionVector(result1.Option);
                if (opvec != null)
                {
                    result1.ValueX = opvec;
                    goto Step1ValueX;
                }
                if (result1.Option.ToUpper() == "A")
                {
                    goto Step3;
                }
                else
                {
                    goto Step1;
                }
            }
            goto Step1;
        Step2:
            this.CurrentType = "Line";
            var step2 = curMethod.Steps[2];
            var result2 = await PointInputer.Execute(step2.Options);
            if (PointInputer.isCancelled)
            {
                return false;
            }
        Step2ValueX:
            if (result2.ValueX != null)
            {
                Vector2 pointB = (Vector2)result2.ValueX;
                Line2d pline = new Line2d();
                var lastLine = curSg.Last();
                var endPoint = lastLine is Line2d ? (lastLine as Line2d).End : (lastLine as Arc2d).GetPoints(1).Last();
                pline.Start = endPoint.Clone();
                pline.End = pointB.Clone();
                curSg.Add(pline);
                if (Utils.Vec2EQ(curSg.Last().GetPoints(1).Last(), curSg.First().GetPoints(1).First(), 0.001))
                {
                    return true;
                }
                goto Step2;
            }
            else
            if (result2.Option != null)
            {
                var opvec = GetOptionVector(result2.Option);
                if (opvec != null)
                {
                    result2.ValueX = opvec;
                    goto Step2ValueX;
                }
                if (result2.Option.ToUpper() == "A")
                {
                    if (curSg.Count >= 2 || curSg.Any(n => n is Arc2d))
                        goto Step4;
                    else
                        goto Step3;
                }
                else if (result2.Option.ToUpper() == "C")
                {
                    Line2d pline = new Line2d();
                    var lastLine = curSg.Last();
                    var first = curSg.First();
                    var endPoint = lastLine is Line2d ? (lastLine as Line2d).End : (lastLine as Arc2d).GetPoints(1).Last();
                    var startPoint = first is Line2d ? (first as Line2d).Start : (first as Arc2d).GetPoints(1).First();
                    pline.Start = endPoint.Clone();
                    pline.End = startPoint.Clone();
                    curSg.Add(pline);
                    return true;
                }
            }
            goto Step2;
        Step3:
            this.CurrentType = "Arc";
            var step3 = curMethod.Steps[3];
            var result3 = await PointInputer.Execute(step3.Options);
            if (PointInputer.isCancelled)
            {
                return false;
            }
        Step3ValueX:
            if (result3.ValueX != null)
            {
                Vector2 currP = (Vector2)result3.ValueX;
                Vector2 lastStart, lastEnd;
                if (curSg.Count > 0)
                {
                    if (curSg.Last() is Line2d lastline)
                    {
                        lastEnd = lastline.End.Clone();
                        lastStart = lastline.Start.Clone();
                    }
                    else
                    {
                        var arc = curSg.Last() as Arc2d;
                        var arcp = arc.GetPoints(100);
                        lastEnd = arcp.Last().Clone();
                        lastStart = arcp[98].Clone();
                    }
                }
                else
                {
                    lastStart = new(this.firstPoint.X - 5, this.firstPoint.Y);
                    lastEnd = this.firstPoint.Clone();
                }

                var cir = GetCircleBylinePoint(lastStart, lastEnd, currP);
                if (cir == null)
                {
                    Line2d line = new Line2d();
                    line.Start = lastEnd;
                    line.End = currP;
                    curSg.Add(line);
                    if (Utils.Vec2EQ(curSg.Last().GetPoints(1).Last(), curSg.First().GetPoints(1).First(), 0.001))
                    {
                        return true;
                    }
                    goto Step3;
                }
                else
                {
                    var arc = new Arc2d();
                    arc.Center = cir.Item1;
                    arc.Radius = Vector2.Distance(cir.Item1, currP);
                    var angle = currP.Clone().Sub(lastEnd).Angle() - lastStart.Clone().Sub(lastEnd).Angle();
                    arc.IsClockwise = angle < -Math.PI || (angle > 0 && angle < Math.PI);
                    arc.StartAngle = lastEnd.Clone().Sub(arc.Center).Angle();
                    arc.EndAngle = currP.Clone().Sub(arc.Center).Angle();
                    if (double.IsNaN(arc.StartAngle) || double.IsNaN(arc.EndAngle))
                    {
                        if (curSg.Count > 1)
                        {
                            goto Step4;
                        }
                        else
                        {
                            goto Step3;
                        }
                    }
                    curSg.Add(arc);
                    if (Utils.Vec2EQ(curSg.Last().GetPoints(1).Last(), curSg.First().GetPoints(1).First(), 0.001))
                    {
                        return true;
                    }
                    goto Step4;
                }
            }
            else if (result3.Option != null)
            {
                var opvec = GetOptionVector(result3.Option);
                if (opvec != null)
                {
                    result3.ValueX = opvec;
                    goto Step3ValueX;
                }
                if (result3.Option.ToUpper() == "L")
                {
                    goto Step1;
                }
                else if (result3.Option.ToUpper() == "CE")
                {
                    goto Step5;
                }
                else if (result3.Option.ToUpper() == "A")
                {
                    goto Step7;
                }
            }
            goto Step3;
        Step4:
            this.CurrentType = "Arc";
            var step4 = curMethod.Steps[4];
            var result4 = await PointInputer.Execute(step4.Options);
            if (PointInputer.isCancelled)
            {
                return false;
            }
        Step4ValueX:
            if (result4.ValueX != null)
            {
                Vector2 currP = (Vector2)result4.ValueX;
                Vector2 lastEnd, lastStart;
                if (curSg.Last() is Line2d lastline)
                {
                    lastEnd = lastline.End.Clone();
                    lastStart = lastline.Start.Clone();
                }
                else
                {
                    var arc = curSg.Last() as Arc2d;
                    var arcp = arc.GetPoints(100);
                    lastEnd = arcp.Last().Clone();
                    lastStart = arcp[98].Clone();
                }

                var cir = GetCircleBylinePoint(lastStart, lastEnd, currP);
                if (cir == null)
                {
                    Line2d line = new Line2d();
                    line.Start = lastEnd;
                    line.End = currP;
                    curSg.Add(line);
                    if (Utils.Vec2EQ(curSg.Last().GetPoints(1).Last(), curSg.First().GetPoints(1).First(), 0.001))
                    {
                        return true;
                    }
                }
                else
                {
                    var arc = new Arc2d();
                    arc.Center = cir.Item1;
                    //arc.Angle = cir.Item3;
                    arc.Radius = Vector2.Distance(cir.Item1, currP);
                    var angle = currP.Clone().Sub(lastEnd).Angle() - lastStart.Clone().Sub(lastEnd).Angle();
                    arc.IsClockwise = angle < -Math.PI || (angle > 0 && angle < Math.PI);
                    arc.StartAngle = lastEnd.Clone().Sub(arc.Center).Angle();
                    arc.EndAngle = currP.Clone().Sub(arc.Center).Angle();
                    if (double.IsNaN(arc.StartAngle) || double.IsNaN(arc.EndAngle))
                    {
                        goto Step4;
                    }
                    curSg.Add(arc);
                }
                if (Utils.Vec2EQ(curSg.Last().GetPoints(1).Last(), curSg.First().GetPoints(1).First(), 0.001))
                {
                    return true;
                }
                goto Step4;

            }
            else if (result4.Option != null)
            {
                var opvec = GetOptionVector(result4.Option);
                if (opvec != null)
                {
                    result4.ValueX = opvec;
                    goto Step4ValueX;
                }
                if (result4.Option.ToUpper() == "L")
                {
                    goto Step2;
                }
                else if (result4.Option.ToUpper() == "CL")
                {
                    Vector2 lastStart, lastEnd;
                    var firstLine = curSg.First();
                    if (curSg.Last() is Line2d lastline)
                    {
                        lastEnd = lastline.End.Clone();
                        lastStart = lastline.Start.Clone();
                    }
                    else
                    {
                        var arc = curSg.Last() as Arc2d;
                        var arcp = arc.GetPoints(100);
                        lastEnd = arcp.Last().Clone();
                        lastStart = arcp[98].Clone();
                    }
                    var fsp = (firstLine is Line2d ? (firstLine as Line2d).Start : (firstLine as Arc2d).GetPoints(1).First()).Clone();
                    //Line2d line = new Line2d();
                    //line.Start = lep.Clone();
                    //line.End = fsp.Clone();
                    var cir = GetCircleBylinePoint(lastStart, lastEnd, fsp);
                    if (cir == null)
                    {
                        Line2d line = new Line2d();
                        line.Start = lastEnd;
                        line.End = fsp;
                        curSg.Add(line);
                    }
                    else
                    {
                        var arc = new Arc2d();
                        arc.Center = cir.Item1;
                        //arc.Angle = cir.Item3;
                        arc.Radius = Vector2.Distance(cir.Item1, fsp);
                        var angle = fsp.Clone().Sub(lastEnd).Angle() - lastStart.Clone().Sub(lastEnd).Angle();
                        arc.IsClockwise = angle < -Math.PI || (angle > 0 && angle < Math.PI);
                        arc.StartAngle = lastEnd.Clone().Sub(arc.Center).Angle();
                        arc.EndAngle = fsp.Clone().Sub(arc.Center).Angle();
                        if (double.IsNaN(arc.StartAngle) || double.IsNaN(arc.EndAngle))
                        {
                            goto Step4;
                        }
                        curSg.Add(arc);
                    }
                    return true;
                }
                else if (result4.Option.ToUpper() == "CE")
                {
                    goto Step5;
                }
                else if (result4.Option.ToUpper() == "A")
                {
                    goto Step7;
                }
            }
            goto Step4;
        Step5:
            this.CurrentType = "Arc-CE";
            var step5 = curMethod.Steps[5];
            var result5 = await PointInputer.Execute(step5.Options);
            if (PointInputer.isCancelled)
            {
                return false;
            }
        Step5ValueX:
            if (result5.ValueX != null)
            {
                CurrentArc = new Arc2d();
                Vector2 center = (Vector2)result5.ValueX;
                CurrentArc.Center = center.Clone();
                Vector2 lastEnd;
                if (curSg.Count > 0)
                {
                    var lastLine = curSg.Last();
                    var endPoint = lastLine is Line2d ? (lastLine as Line2d).End : (lastLine as Arc2d).GetPoints(1).Last();
                    lastEnd = endPoint.Clone();
                }
                else
                {
                    lastEnd = this.firstPoint.Clone();
                }
                CurrentArc.Radius = center.DistanceTo(lastEnd);
                CurrentArc.StartAngle = lastEnd.Clone().Sub(center).Angle();
                if (curSg.Count > 0)
                {
                    goto Step6;
                }
                else
                {
                    goto Step9;
                }
            }
            else
            {
                var opvec = GetOptionVector(result5.Option);
                if (opvec != null)
                {
                    result5.ValueX = opvec;
                    goto Step5ValueX;
                }
            }
            goto Step5;
        Step6:
            var step6 = curMethod.Steps[6];
            var result6 = await PointInputer.Execute(step6.Options);
            if (PointInputer.isCancelled)
            {
                return false;
            }
        Step6ValueX:
            if (result6.ValueX != null)
            {
                Vector2 end = (Vector2)result6.ValueX;
                CurrentArc.EndAngle = end.Clone().Sub(CurrentArc.Center).Angle();
                curSg.Add(CurrentArc.Clone());
                if (Utils.Vec2EQ(curSg.Last().GetPoints(1).Last(), curSg.First().GetPoints(1).First(), 0.001))
                {
                    return true;
                }
                CurrentArc = null;
                goto Step4;
            }
            else if (result6.Option != null)
            {
                var opvec = GetOptionVector(result6.Option);
                if (opvec != null)
                {
                    result6.ValueX = opvec;
                    goto Step6ValueX;
                }
                if (result6.Option.ToUpper() == "C")
                {
                    CurrentArc.IsClockwise = !CurrentArc.IsClockwise;
                }
            }
            goto Step6;
        Step9:
            var step9 = curMethod.Steps[9];
            var result9 = await PointInputer.Execute(step9.Options);
            if (PointInputer.isCancelled)
            {
                return false;
            }
        Step9ValueX:
            if (result9.ValueX != null)
            {
                Vector2 end = (Vector2)result9.ValueX;
                CurrentArc.EndAngle = end.Clone().Sub(CurrentArc.Center).Angle();
                curSg.Add(CurrentArc.Clone());
                if (Utils.Vec2EQ(curSg.Last().GetPoints(1).Last(), curSg.First().GetPoints(1).First(), 0.001))
                {
                    return true;
                }
                CurrentArc = null;
                goto Step4;
            }
            else if (result9.Option != null)
            {
                var opvec = GetOptionVector(result9.Option);
                if (opvec != null)
                {
                    result9.ValueX = opvec;
                    goto Step9ValueX;
                }
                if (result9.Option.ToUpper() == "C")
                {
                    CurrentArc.IsClockwise = !CurrentArc.IsClockwise;
                }
                if (result9.Option.ToUpper() == "CL")
                {
                    CurrentArc.EndAngle = CurrentArc.IsClockwise ? CurrentArc.StartAngle - Utils.TwoPI : CurrentArc.StartAngle + Utils.TwoPI;
                    curSg.Add(CurrentArc.Clone());
                    return true;
                }
            }
            goto Step9;
        Step7:
            CurrentType = "Arc-Angel";
            var step7 = curMethod.Steps[7];
            var result7 = await PointInputer.Execute(step7.Options);
            if (PointInputer.isCancelled)
            {
                return false;
            }
            if (result7.Option != null && double.TryParse(result7.Option.Trim(), out var sweepAngle))
            {
                this.SweepAngle = sweepAngle;
            }
            goto Step7;
        Step8:
            CurrentType = "Arc-Angel";
            var step8 = curMethod.Steps[8];
            var result8 = await PointInputer.Execute(step8.Options);
            if (PointInputer.isCancelled)
            {
                return false;
            }

            goto Step8;
        Step10:
            CurrentType = "Circle";
            var step10 = curMethod.Steps[10];
            var result10 = await PointInputer.Execute(step10.Options);
            if (PointInputer.isCancelled)
            {
                return false;
            }
        Step10ValueX:
            if (result10.ValueX != null)
            {
                CurrentArc = new Arc2d();
                this.firstPoint = (Vector2)result10.ValueX;
                CurrentArc.Center = this.firstPoint.Clone();
                CurrentArc.StartAngle = 0;
                CurrentArc.EndAngle = Math.PI * 2;
            }
            else
            {
                var opvec = GetOptionVector(result10.Option);
                if (opvec != null)
                {
                    result10.ValueX = opvec;
                    goto Step10ValueX;
                }
            }
            goto Step11;
        Step11:
            CurrentType = "Circle";
            var step11 = curMethod.Steps[11];
            var result11 = await PointInputer.Execute(step11.Options);
            if (PointInputer.isCancelled)
            {
                return false;
            }
        Step11ValueX:
            if (result11.ValueX != null)
            {
                Vector2 cp = (Vector2)result11.ValueX;
                CurrentArc.Radius = cp.DistanceTo(CurrentArc.Center);
                curSg.Add(CurrentArc.Clone());
                CurrentArc = null;
                return true;
            }
            else
            {
                var opvec = GetOptionVector(result11.Option);
                if (opvec != null)
                {
                    result11.ValueX = opvec;
                    goto Step11ValueX;
                }
            }
            goto Step11;
        }
        private Vector2 GetOptionVector(string Option)
        {
            if (!string.IsNullOrEmpty(Option))
            {
                var xyz = Option.split(",");
                if (double.TryParse(xyz[0].Trim(), out var pX) && double.TryParse(xyz[1].Trim(), out var pY))
                {
                    return new Vector2(pX, pY);
                }
            }
            return null;
        }
        public async void ExecCreate(string[] args = null)
        {
            this.StartCreating();
            this.PointInputer = new PointInputer(this.docEditor);
            var columnInstance = new QdColumnInstance(ComponentManager.GetCptDef<QdColumnDef>("结构柱", "结构柱", ColumnAttribute.BuiltinUuid));
            columnInstance.Height = 800;
            columnInstance.Bottom = 0; 
            var curMethod = CreateMethods[0];
            Segments = new List<Curve2d>();
            var succes = await Creating(curMethod, Segments);
            if (succes)
            {
                var isClockWise = ShapeUtils.isClockWise(Segments.SelectMany(n => n.GetPoints((n is Arc2d ? 32 : 1))).ToListEx());
                var newShape = new List<Curve2d>();
                if (isClockWise)
                {
                    for (var i = Segments.Count() - 1; i >= 0; i--)
                    {
                        var cur = Segments[i];
                        //cur.Translate(offset);
                        if (isClockWise)
                        {
                            cur.Reverse();
                            newShape.Add(cur.Clone());
                        }
                    }
                    Segments = newShape;
                }
                columnInstance.Lines = Segments.ToArray();
                this.DrawColumn(columnInstance);
            }

        End:
            this.PointInputer = null;
            CurrentArc = null;
            Segments = null;
            this.EndCreating();
        }
     
        public override void Draw(SKCanvas canvas, LcElement element, Vector2 offset)
        {
            var columnInstance = element as QdColumnInstance;
            var curves = columnInstance.Curves?.FirstOrDefault().Curve2ds;
            var pen = this.GetDrawPen(element);
            if (pen == LightCAD.Runtime.Constants.defaultPen)
            {
                pen = new SKPaint { Color = SKColors.White, IsStroke = true };
            }
            DrawColumnCurves(canvas, curves, pen);
        }
        public override void Draw(SKCanvas canvas, LcElement element, Matrix3 matrix)
        {
            var columnInstance = element as QdColumnInstance;
            // var curves = columnInstance.ShapeCurves;
            var curves = columnInstance.Curves?.FirstOrDefault().Curve2ds;
            var pen = this.GetDrawPen(element);
            if (pen == LightCAD.Runtime.Constants.defaultPen)
            {
                pen = new SKPaint { Color = SKColors.White, IsStroke = true };
            }
            DrawColumnCurves(canvas,curves,pen);
        }
        public void DrawColumnCurves(SKCanvas canvas, List<Curve2d> curves, SKPaint pen)
        {
            foreach (var curve in curves)
            {
                switch (curve.Type)
                {
                    case Curve2dType.Arc2d:
                        {
                            var arc = curve as Arc2d;
                            Matrix3 matrix = Matrix3.GetTranslate(new Vector2(0, 0));
                            this.vportRt.DrawArc(arc, matrix,canvas, pen);
                            break;
                        }
                    case Curve2dType.Line2d:
                        {
                            var line = curve as Line2d;
                            Matrix3 matrix = Matrix3.GetTranslate(new Vector2(0, 0));
                            var start = this.vportRt.ConvertWcsToScr(line.Start).ToSKPoint();
                            var end = this.vportRt.ConvertWcsToScr(line.End).ToSKPoint();
                            canvas.DrawLine(start,end,pen);
                            break;
                        }
                    default:
                        break;
                }
            }

        }
         private void DrawColumn(QdColumnInstance columnInstance) 
        {
            if (columnInstance == null)
                return;
            columnInstance.Initilize(this.docRt.Document);
            this.docRt.Document.ModelSpace.InsertElement(columnInstance);
        }
        public override void Cancel()
        {
            base.Cancel();
            this.vportRt.SetCreateDrawer(null);
        }
        public override void DrawAuxLines(SKCanvas canvas)
        {
            var mp = this.vportRt.PointerMovedPosition.ToVector2d();
            var wcs_mp = this.vportRt.ConvertScrToWcs(mp);
            var sk_p = this.vportRt.ConvertWcsToScr(wcs_mp).ToSKPoint();
            foreach (var ele in Segments)
            {
                if (ele is Line2d line)
                {
                    var start = this.vportRt.ConvertWcsToScr(line.Start).ToSKPoint();
                    var end = this.vportRt.ConvertWcsToScr(line.End).ToSKPoint();
                    using (var elePen = new SKPaint { Color = SKColors.Green, IsStroke = true })
                    {
                        canvas.DrawLine(start, end, elePen);
                    }
                }
                else if (ele is Arc2d arc)
                {
                    using (var elePen = new SKPaint { Color = SKColors.Green, IsStroke = true })
                    {
                        Matrix3 matrix = Matrix3.GetTranslate(new Vector2(0, 0));
                        this.vportRt.DrawArc(arc, matrix, canvas, elePen);
                    }
                }
            }
            Vector2 startpoint = new Vector2(0, 0);//上一个元素的开始点
            Vector2 lastStart;
            if (this.firstPoint == null)
                return;
            if (Segments.Count == 0)
            {
                startpoint = this.firstPoint.Clone();
                lastStart = new Vector2(this.firstPoint.X - 5, this.firstPoint.Y);
            }
            else
            {
                if (Segments.Last() is Line2d lastline)
                {
                    startpoint = lastline.End.Clone();
                    lastStart = lastline.Start.Clone();
                }
                else
                {
                    var arc = Segments.Last() as Arc2d;
                    var arcp = arc.GetPoints(100);
                    startpoint = arcp.Last().Clone();
                    lastStart = arcp[98].Clone();
                }
            }
            if (CurrentType == "Arc")
            {
                var cir = GetCircleBylinePoint(lastStart, startpoint, wcs_mp);
                if (cir == null)
                {
                    using (var elePen = new SKPaint { Color = SKColors.Gray, IsStroke = true })
                    {
                        canvas.DrawLine(this.vportRt.ConvertWcsToScr(startpoint).ToSKPoint(), sk_p, elePen);
                    }
                    return;
                }
                var arc = new Arc2d();
                arc.Center = cir.Item1.Clone();
                arc.Radius = startpoint.DistanceTo(arc.Center);
                var angle = wcs_mp.Clone().Sub(startpoint).Angle() - lastStart.Clone().Sub(startpoint).Angle();
                arc.IsClockwise = angle < -Math.PI || (angle > 0 && angle < Math.PI);
                arc.StartAngle = startpoint.Clone().Sub(arc.Center).Angle();
                arc.EndAngle = wcs_mp.Clone().Sub(arc.Center).Angle();
                if (double.IsNaN(arc.StartAngle) || double.IsNaN(arc.EndAngle))
                {
                    return;
                }
                using (var elePen = new SKPaint { Color = SKColors.Gray, IsStroke = true })
                {
                    //arc.EndAngle = wcs_mp.Sub(arc.Center).Angle();
                    //var lcenter = this.vportRt.ConvertWcsToScr(arc.Center).ToSKPoint();
                    //double lradius = Math.Sqrt(Math.Pow(lcenter.X - sk_p.X, 2) + Math.Pow(lcenter.Y - sk_p.Y, 2));
                    //float lx1 = (float)(lcenter.X - lradius);
                    //float ly1 = (float)(lcenter.Y - lradius);
                    //float lx2 = (float)(lcenter.X + lradius);
                    //float ly2 = (float)(lcenter.Y + lradius);
                    Matrix3 matrix = Matrix3.GetTranslate(new Vector2(0, 0));
                    this.vportRt.DrawArc(arc, matrix, canvas, elePen);
                }
                using (var elePen = new SKPaint { Color = SKColors.Yellow, IsStroke = true, PathEffect = SKPathEffect.CreateDash(new float[] { 10, 10, 30, 10 }, 0) })
                {
                    canvas.DrawLine(this.vportRt.ConvertWcsToScr(startpoint).ToSKPoint(), sk_p, elePen);
                }
            }
            else if (CurrentType == "Arc-CE")
            {
                if (CurrentArc == null)
                {
                    using (var elePen = new SKPaint { Color = SKColors.Gray, IsStroke = true })
                    {
                        canvas.DrawLine(this.vportRt.ConvertWcsToScr(startpoint).ToSKPoint(), sk_p, elePen);
                    }
                }
                else
                {
                    using (var elePen = new SKPaint { Color = SKColors.Gray, IsStroke = true })
                    {
                        Matrix3 matrix = Matrix3.GetTranslate(new Vector2(0, 0));
                        var arc = CurrentArc.Clone() as Arc2d;
                        arc.EndAngle = wcs_mp.Sub(arc.Center).Angle();
                        this.vportRt.DrawArc(arc, matrix, canvas, elePen);
                        //var lcenter =  this.vportRt.ConvertWcsToScr(arc.Center).ToSKPoint();
                        //double lradius = Math.Sqrt(Math.Pow(lcenter.X - sk_p.X, 2) + Math.Pow(lcenter.Y - sk_p.Y, 2));
                        //float lx1 = (float)(lcenter.X - lradius);
                        //float ly1 = (float)(lcenter.Y - lradius);
                        //float lx2 = (float)(lcenter.X + lradius);
                        //float ly2 = (float)(lcenter.Y + lradius);
                        //SKRect lskrect = new SKRect(lx1, ly1, lx2, ly2);
                        //canvas.DrawArc(lskrect,(float)arc.StartAngle, (float)arc.EndAngle,false,elePen);
                    }
                }
            }
            else if (CurrentType == "Circle")
            {
                if (CurrentArc != null)
                {
                    using (var elePen = new SKPaint { Color = SKColors.Gray, IsStroke = true })
                    {
                        var arc = CurrentArc.Clone() as Arc2d;
                        arc.Radius = (float)wcs_mp.DistanceTo(CurrentArc.Center);
                        Matrix3 matrix = Matrix3.GetTranslate(new Vector2(0, 0));
                        this.vportRt.DrawArc(arc, matrix, canvas, elePen);
                    }
                }
            }
            else
            {

                using (var elePen = new SKPaint { Color = SKColors.Gray, IsStroke = true })
                {
                    canvas.DrawLine(this.vportRt.ConvertWcsToScr(startpoint).ToSKPoint(), sk_p, elePen);
                }
            }
        }
        #region Grip
        private string _gripName;
        private Vector2 _position;
        public override SnapPointResult SnapPoint(SnapRuntime snapRt, LcElement element, Vector2 point, bool forRef, Vector2 PrePoint = null)
        {

            var maxDistance = vportRt.GetSnapMaxDistance();
            var column = element as QdColumnInstance;
            var sscur = SnapSettings.Current;
            var result = new SnapPointResult { Element = element };
            if (sscur.ObjectOn && column.Lines.Length > 0)
            {
                var firstP = column.Lines.First().GetPoints(0).First().Clone();
                if (Utils.Vec2EQ(firstP, point, maxDistance))
                {
                    result.Point = firstP;
                    result.Name = "Start";
                    result.Curves.Add(new SnapRefCurve(SnapPointType.Endpoint, column.Lines.First().Clone()));
                }
                
            }
            if (result.Point != null)
                return result;
            else
                return null;
        }
        public override ControlGrip[] GetControlGrips(LcElement element)
        {
            var columnInstance = element as QdColumnInstance;
            var grips = new List<ControlGrip>(); 
            for (var i = 0; i < columnInstance.Lines.Length; i++)
            {
                var curve = columnInstance.Lines[i];
                var points = curve.GetPoints(2);
                grips.Add(new ControlGrip()
                {
                    Element = columnInstance,
                    Name = "SecGrip_Start_" + i,
                    Position = points[0].Clone()
                });
                grips.Add(new ControlGrip()
                {
                    Element = columnInstance,
                    Name = "SecGrip_Center_" + i,
                    Position = points[1].Clone()
                });
            } 
            return grips.ToArray();
        }

        public override void SetDragGrip(LcElement element, string gripName, Vector2 position, bool isEnd)
        {
            var columnInstance = element as QdColumnInstance;
            _columnInstance = columnInstance;
            if (!isEnd)
            {
                if (_columnInstance == null)
                {
                    _columnInstance = columnInstance.Clone() as QdColumnInstance;
                }
                _gripName = gripName;
                _position = position;
                var type = gripName.Substring(0, gripName.IndexOf("_"));
                var grips = gripName.split("_");
                var index = int.Parse(grips[2]);
                var curve = _columnInstance.Lines[index];
                var curCurve = columnInstance.Lines[index];
                UpdateSegment(curve, curCurve, columnInstance.Lines, _columnInstance.Lines, position, index, grips);

            }
            else
            {
                _columnInstance = null;
            }

        }
        /// <summary>
        /// 更新当前轮廓
        /// </summary>
        /// <param name="curve">复制记录移动之前的线段</param>
        /// <param name="curCurve">当前线段</param>
        /// <param name="current">当前轮廓</param>
        /// <param name="copy">复制的轮廓</param>
        /// <param name="position"></param>
        /// <param name="index"></param>
        /// <param name="grips"></param>
        private void UpdateSegment(Curve2d curve, Curve2d curCurve, Curve2d[] current,Curve2d[] copy, Vector2 position, int index, List<string> grips)
        {
            if (grips.Contains("Center"))
            {
                if (curve is Arc2d)
                {
                    var curArc = curCurve as Arc2d;
                    var points = curve.GetPoints(2);
                    UpdateArc2dByPoints(ref curArc, points[0], position.Clone(), points[2]);
                }
                else
                {
                    //var line = curve as Line2d;
                    var curLine = curCurve as Line2d;
                    var offset = position.Clone().Sub(curLine.GetPoints(2)[1]);
                    curLine.Translate(offset);
                    Curve2d curLast = index == 0 ? current.Last() : current[index - 1];
                    Curve2d curLastCopy = index == 0 ? copy.Last() : copy[index - 1];
                    Curve2d curNext = index == current.Length - 1 ? current.First() : current[index + 1];
                    Curve2d curNextCopy = index == current.Length - 1 ? copy.First() : copy[index + 1];

                    //当轮廓线数量为2时，另一条线必定为曲线
                    if (current.Length == 2)
                    {
                        var curLastArc = curLast as Arc2d;
                        var newMdi = curLastCopy.GetPoints(2)[1];
                        UpdateArc2dByPoints(ref curLastArc, curLine.End.Clone(), newMdi, curLine.Start.Clone());
                    }
                    else
                    {
                        if (curLast is Arc2d curLastArc)
                        {
                            var points = curLastCopy.GetPoints(2);
                            UpdateArc2dByPoints(ref curLastArc, points[0], points[1], curLine.Start.Clone());
                        }
                        else if (curLast is Line2d curLastLine)
                        {
                            curLastLine.End = curLine.Start.Clone();
                        }
                        if (curNext is Arc2d curNextArc)
                        {
                            var points = curNextCopy.GetPoints(2);
                            UpdateArc2dByPoints(ref curNextArc, curLine.End.Clone(), points[1], points[2]);
                        }
                        else if (curNext is Line2d curNextLine)
                        {
                            curNextLine.Start = curLine.End.Clone();
                        }
                    }
                }
            }
            else
            {
                if (curve is Arc2d)
                {
                    var curArc = curCurve as Arc2d;
                    var points = curve.GetPoints(2);
                    UpdateArc2dByPoints(ref curArc, position.Clone(), points[1], points[2]);
                }
                else
                {
                    var line = current[index] as Line2d;
                    line.Start = position.Clone();
                }
                Curve2d curLine = index == 0 ? current.Last() : current[index - 1];
                Curve2d curLineCopy = index == 0 ? copy.Last() : copy[index - 1];
                if (curLine is Line2d lastline)
                {
                    lastline.End = position.Clone();
                }
                else if (curLine is Arc2d lastArc)
                {
                    var points = curLineCopy.GetPoints(2);
                    UpdateArc2dByPoints(ref lastArc, points[0], points[1], position.Clone());
                }
            }
        }
        private void UpdateArc2dByPoints(ref Arc2d curArc, Vector2 start, Vector2 mdi, Vector2 end)
        {
            var center = GetCircleCenter(mdi, start, end);
            var radius = center.DistanceTo(mdi);
            var startAngle = start.Clone().Sub(center).Angle();
            var endAngle = end.Clone().Sub(center).Angle();
            var mdiAngle = mdi.Clone().Sub(start).Angle();
            var lastAngle = end.Clone().Sub(start).Angle();
            var angle = mdiAngle - lastAngle;
            curArc.IsClockwise = angle < -Math.PI || (angle > 0 && angle < Math.PI);
            curArc.Radius = radius;
            curArc.StartAngle = startAngle;
            curArc.EndAngle = endAngle;
            curArc.Center = center;
        }
        public override List<PropertyObserver> GetPropertyObservers()
        {
            //return base.GetPropertyObservers();
            var list = new List<PropertyObserver>() {
              new PropertyObserver()
            {
                Name = "Height",
                DisplayName = "高度",
                CategoryName = "Geometry",
                CategoryDisplayName = "几何图形",
                PropType=PropertyType.Double,
                Getter = (ele) => (ele as QdColumnInstance).Parameters.GetValue<double>("Height"),
                Setter = (ele, value) =>
                {
                    var column = (ele as QdColumnInstance);
                    if (!double.TryParse(value.ToString(),out var height)||height<0)
                        return;
                    column.OnPropertyChangedBefore("Height",column.Parameters.GetValue<double>("Height"),height);
                    column.Parameters.SetValue("Height",height );
                    column.ResetCache();
                    column.OnPropertyChangedAfter("Height",column.Parameters.GetValue<double>("Height"),height);
                }
            },  new PropertyObserver()
            {
                Name = "Bottom",
                DisplayName = "底高度",
                CategoryName = "Geometry",
                CategoryDisplayName = "几何图形",
                PropType=PropertyType.Double,
                Getter = (ele) => (ele as QdColumnInstance).Parameters.GetValue<double>("Bottom"),
                Setter = (ele, value) =>
                {
                    var column = (ele as QdColumnInstance);
                    if (!double.TryParse(value.ToString(),out var bottom)||bottom<0)
                        return;
                    column.OnPropertyChangedBefore("Bottom",column.Parameters.GetValue<double>("Bottom"),bottom);
                    column.Parameters.SetValue("Bottom",bottom );
                    column.ResetCache();
                    column.OnPropertyChangedAfter("Bottom",column.Parameters.GetValue<double>("Bottom"),bottom);
                }
            },
            };
            return list;
        }
        public override void DrawDragGrip(SKCanvas canvas)
        {
            if (_columnInstance == null)
                return;
            if (_gripName == "InsertPoint")
            {
                var offset = _position - _columnInstance.Position.ToVector2();
              //  var matrix = Matrix3.GetTranslate(offset) * _columnInstance.Matrix;
                var curves = _columnInstance.Curves?.FirstOrDefault().Curve2ds;
                var pen = this.GetDrawPen(_columnInstance);
                if (pen == LightCAD.Runtime.Constants.defaultPen)
                {
                    pen = new SKPaint { Color = SKColors.White, IsStroke = true };
                }
                DrawColumnCurves(canvas, curves, pen);
            }

        }
        #endregion
        /// <summary>
        /// 通过圆上三点求圆心
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="c"></param>
        /// <returns></returns>
        private Vector2 GetCircleCenter(Vector2 a, Vector2 b, Vector2 c)
        {
            double a13 = a.X - c.X;
            double a13_ = a.X + c.X;
            double b13 = a.Y - c.Y;
            double b13_ = a.Y + c.Y;
            double a12 = a.X - b.X;
            double a12_ = a.X + b.X;
            double b12 = a.Y - b.Y;
            double b12_ = a.Y + b.Y;

            double a12b12_2 = a12 * a12_ + b12 * b12_;
            double a13b13_2 = a13 * a13_ + b13 * b13_;

            double a13b12 = 2 * a13 * b12;
            double a12b13 = 2 * a12 * b13;


            if (a12b13 - a13b12 == 0) return new Vector2((b.X + a.X) / 2, (b.Y + a.Y) / 2);
            double af = a12b13 - a13b12;
            double bf = a13b12 - a12b13;
            double az = b13 * a12b12_2 - b12 * a13b13_2;
            double bz = a13 * a12b12_2 - a12 * a13b13_2;
            double x = az / af;
            double y = bz / bf;
            return new Vector2(x, y);
        }
        public Tuple<Vector2, Vector2, double> GetCircleBy2PD(Vector2 start, Vector2 End, double degrees)
        {
            double point1X = start.X;
            double point1Y = start.Y;
            double point2X = End.X;
            double point2Y = End.Y;
            double angleDegrees = degrees;

            // 计算中点坐标
            double midPointX = (point1X + point2X) / 2;
            double midPointY = (point1Y + point2Y) / 2;

            // 计算两个点之间的距离
            double distance = Math.Sqrt(Math.Pow(point2X - point1X, 2) + Math.Pow(point2Y - point1Y, 2));

            // 将角度转换为弧度
            double radians = angleDegrees * Math.PI / 180;

            double radius = distance / (2 * Math.Sin(radians / 2));
            //// 计算圆心的偏移量
            //double offsetX = distance * Math.Cos(radians);
            //double offsetY = distance * Math.Sin(radians);
            double centerX = midPointX + radius * Math.Cos(radians / 2);
            double centerY = midPointY + radius * Math.Sin(radians / 2);
            // 计算圆心的坐标
            //double centerX = midPointX + offsetX;
            //double centerY = midPointY + offsetY;
            //double radius = Math.Sqrt(Math.Pow(centerX - point1X, 2) + Math.Pow(centerY - point1Y, 2));


            double dx = point2X - point1X;
            double dy = point2Y - point1Y;

            ///# 将向量差单位化
            double unit_dx = dx / distance;
            double unit_dy = dy / distance;

            ///# 计算圆心坐标
            double h = midPointX + radius * unit_dx;
            double k = midPointY + radius * unit_dy;

            var b = start;
            var a = End;
            var r = radius;

            double c1 = (b.X * b.X - a.X * a.X + b.Y * b.Y - a.Y * a.Y) / (2 * (b.X - a.X));
            double c2 = (b.Y - a.Y) / (b.X - a.X);
            double A = (c2 * c2 + 1);
            double B = (2 * a.X * c2 - 2 * c1 * c2 - 2 * a.Y);
            double C = a.X * a.X - 2 * a.X * c1 + c1 * c1 + a.Y * a.Y - r * r;
            Vector2 center1 = new Vector2();
            Vector2 center2 = new Vector2();

            center1.Y = (-B - Math.Sqrt(B * B - 4 * A * C)) / (2 * A);

            center2.Y = (-B + Math.Sqrt(B * B - 4 * A * C)) / (2 * A);

            center1.X = c1 - c2 * center1.Y;
            center2.X = c1 - c2 * center2.Y;
            return new Tuple<Vector2, Vector2, double>(center1, center2, radius);
        }
        /// <summary>
        /// 切线加终止点画弧线  返回圆心和角度
        /// </summary>
        /// <param name="lineStart"></param>
        /// <param name="lineEnd"></param>
        /// <param name="point"></param>
        /// <returns>  圆心，半径，弧度</returns>
        public Tuple<Vector2, double, double> GetCircleBylinePoint(Vector2 lineStart, Vector2 lineEnd, Vector2 point)
        {
            int tp = IsTopInLine(lineStart, lineEnd, point);
            if (tp == 0)
            {
                return null;//在同一条线上画直线
            }

            double Degrees = GetDegreesByTwoLine(lineStart, lineEnd, lineEnd, point);

            Degrees = 180 - (90 - Degrees) * 2;

            Tuple<Vector2, Vector2, double> cirTuple = GetCircleBy2PD(lineEnd, point, Degrees);
            int tc = IsTopInLine(lineEnd, point, cirTuple.Item1);
            Vector2 circenter;
            if (Degrees < 180)//圆心和线要在同一边 当弧度小于半圆，大于半圆时 ，向量反之  
            {
                if (tc == tp)
                    circenter = cirTuple.Item1;
                else circenter = cirTuple.Item2;
            }
            else
            {
                if (tc != tp)
                    circenter = cirTuple.Item1;
                else circenter = cirTuple.Item2;
            }
            /// 圆心，半径，弧度
            return new Tuple<Vector2, double, double>(circenter, cirTuple.Item3, Degrees);
        }


        /// <summary>
        /// 获取两条线的夹角  
        /// </summary>
        /// <param name="line1start"></param>
        /// <param name="line1End"></param>
        /// <param name="line2start"></param>
        /// <param name="line2End"></param>
        /// <returns></returns>
        public double GetDegreesByTwoLine(Vector2 line1start, Vector2 line1End, Vector2 line2start, Vector2 line2End)
        {
            double x1 = line1start.X;
            double y1 = line1start.Y;
            double x2 = line1End.X;
            double y2 = line1End.Y;
            double x3 = line2start.X;
            double y3 = line2start.Y;
            double x4 = line2End.X;
            double y4 = line2End.Y;

            // 计算线段的向量表示
            double v1x = x2 - x1;
            double v1y = y2 - y1;
            double v2x = x4 - x3;
            double v2y = y4 - y3;

            // 计算向量的内积
            double dotProduct = v1x * v2x + v1y * v2y;

            // 计算向量的长度
            double magnitudeV1 = Math.Sqrt(v1x * v1x + v1y * v1y);
            double magnitudeV2 = Math.Sqrt(v2x * v2x + v2y * v2y);

            // 计算夹角余弦值
            double cosine = dotProduct / (magnitudeV1 * magnitudeV2);

            // 将夹角余弦值转换为角度
            double angleRadians = Math.Acos(cosine);
            double angleDegrees = angleRadians * 180 / Math.PI;
            return angleDegrees;
        }
        public int IsTopInLine(Vector2 line1start, Vector2 line1End, Vector2 point)
        {
            Vector2 S;
            Vector2 E;
            //if (line1start.X < line1End.X)
            //{
            //    S = line1start;
            //    E = line1End;

            //}
            //else
            //   if (line1start.X == line1End.X)
            //{
            //    if (line1start.Y < line1End.Y)
            //    {
            //        S = line1start;
            //        E = line1End;

            //    }
            //    else
            //    {
            //        S = line1End;
            //        E = line1start;


            //    }
            //}
            //else
            //{
            S = line1End;
            E = line1start;

            // }
            double Tmp = (S.Y - E.Y) * point.X + (E.X - S.X) * point.Y + S.X * E.Y - E.X * S.Y;
            if (Tmp == 0)
            {
                return 0;
            }
            if (Tmp > 0)
            {
                return 1;
            }
            else
            { return -1; }
            //                Tmp > 0 在左侧

            //Tmp = 0 在线上

            //Tmp < 0 在右侧
        }
    }
    public class Column3dAction : ComponentInstance3dAction
    {
        private Surface3d GenerateSurface(Curve3d top, Curve3d curve)
        {
            if (curve is Arc3d arc)
            {
                var topArc = top as Arc3d;
                //var origin = arc.Center.Clone().AddScaledVector(profile.Normal.Clone().Normalize().Negate(),depth);
                var origin = arc.Center.Clone();
                var normal = topArc.Center.Clone().Sub(arc.Center).Normalize();
                return new CylindricalSurface3d(topArc.Radius, arc.Radius, arc.Center.DistanceTo(topArc.Center), arc.IsClockwise ? arc.EndAngle : arc.StartAngle, arc.IsClockwise ? arc.StartAngle : arc.EndAngle, origin, normal, 32, arc.IsClockwise);
            }
            if (curve is Line3d)
            {
                var topLine = top as Line3d;
                var bottomLine = curve.Clone().Reverse() as Line3d;
                var xAxis = topLine.End.Clone().Sub(topLine.Start).Normalize();
                var yAxis = topLine.Start.Clone().Sub(bottomLine.End).Cross(xAxis).Normalize().Negate();
                var leftLine = new Line3d(topLine.End.Clone(), bottomLine.Start.Clone());
                var rightLine = new Line3d(bottomLine.End.Clone(), topLine.Start.Clone());
                return new PlanarSurface3d(new Plane(yAxis), new List<Curve3d>() { topLine.Clone(), leftLine, bottomLine.Clone(), rightLine });
            }
            return null;
        }
        public override List<Object3D> Render(IComponentInstance cptIns)
        {
            try
            {
                var column = cptIns as QdColumnInstance;
                var result = new List<Object3D>();
                var lcMats = column.Definition.Solid3dProvider.AssignMaterialsFunc(cptIns, null);
                if (column.Lines != null)
                {

                    var topLoop = column.Lines.Select(n =>
                    {
                        Curve3d curve;
                        if (n is Line2d line)
                        {
                            curve = new Line3d(line.Start.ToVector3(column.Bottom + column.Height), line.End.ToVector3(column.Bottom + column.Height));
                        }
                        else
                        {
                            var arc = n as Arc2d;
                            curve = new Arc3d(arc.Center.ToVector3(column.Bottom + column.Height), arc.Radius, arc.StartAngle, arc.EndAngle, arc.IsClockwise);
                        }
                        return curve;
                    }).ToList();
                    var topFace = new PlanarSurface3d(new Plane(new Vector3(0,0,1)), topLoop);
                    var bottomFace = new PlanarSurface3d(new Plane(new Vector3(0, 0, -1)), topLoop.Select(n=>n.Clone().Translate(0,0,-column.Height)).ToList());
                    var aroundFaces = new List<Surface3d>();
                    aroundFaces.Add(topFace);
                    aroundFaces.Add(bottomFace);
                    for (var i = 0; i < topLoop.Count; i++)
                    {
                        var curve = topFace.OuterLoop[i].Clone();
                        var btmCurve = bottomFace.OuterLoop[i].Clone();
                        var surface = GenerateSurface(curve, btmCurve);
                        aroundFaces.Add(surface);
                    }
                    var posArr = new ListEx<double>();
                    var idxArr = new ListEx<int>();
                    int idxOffset = 0;
                    for (int i = 0; i < aroundFaces.Count; i++)
                    {
                        var face = aroundFaces[i];
                        var tuple = face.Trianglate();
                        idxOffset = posArr.Length / 3;
                        posArr.AddRange(tuple.Item1);
                        idxArr.AddRange(tuple.Item2.Select(idx => idx + idxOffset));
                    }
                    GeometryData geometryData = new GeometryData();
                    geometryData.Position = posArr;
                    geometryData.Index = idxArr;
                    var geo = geometryData.GetBufferGeometry();
                    geo.name = "Column";
                    geo.computeVertexNormals();
                    geo.SetUV();
                    var mesh = new Mesh(geo, lcMats.Select(m => RenderMaterialManager.GetRenderMaterial(m.Uuid)).ToArray());
                    mesh.position.Set(column.Transform3d.Position.X, column.Transform3d.Position.Y, column.Transform3d.Position.Z);
                    result.Add(mesh);
                }
                return result;
            }
            catch (Exception ex)
            {

            }
            return null;
        }

    }
}
